// utils/request.ts

interface RequestConfig {
  url: string;
  method?: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'OPTIONS' | 'HEAD' | 'TRACE' | 'CONNECT';
  data?: any;
  header?: Record<string, string>;
  timeout?: number;
  baseURL?: string;
  // 是否禁用节流（默认启用节流）
  disableThrottle?: boolean;
  // 响应类型
  responseType?: 'text' | 'json' | 'arraybuffer';
}

interface ApiResponse<T = any> {
  code: number;
  msg: string;
  data: T;
}

// 图片响应接口
interface ImageResponse {
  imageData: string; // base64格式的图片数据
}

const DEFAULT_CONFIG: Partial<RequestConfig> = {
  // baseURL: 'http://120.26.105.183:8081', // 默认请求地址
  baseURL: 'https://api.zljdhome.com/app-api', // 默认请求地址
  timeout: 10000,                    // 默认超时时间
  header: {
    'Content-Type': 'application/json',
    'Accept': 'application/json'
  }
};

// 正在进行的请求映射
const pendingRequests = new Map<string, Promise<ApiResponse<any>>>();

/**
 * 生成请求的唯一标识符
 * @param config 请求配置
 * @returns 请求标识符
 */
const generateRequestKey = (config: RequestConfig): string => {
  const { url, method = 'GET', data } = config;
  // 将数据序列化为字符串，如果没有数据则使用空字符串
  const dataStr = data ? JSON.stringify(data) : '';
  return `${method}:${url}:${dataStr}`;
};

/**
 * 封装 uni.request 请求
 * @param options 请求配置
 * @returns Promise<ApiResponse>
 */
const request = async <T = any>(options: RequestConfig): Promise<ApiResponse<T>> => {
  const config: RequestConfig = {
    ...DEFAULT_CONFIG,
    ...options,
    header: {
      ...DEFAULT_CONFIG.header,
      ...options.header
    }
  };

  // 拼接完整 URL
  if (!config.url.startsWith('http')) {
    config.url = config.baseURL + config.url;
  }

  // 生成请求唯一标识符
  const requestKey = generateRequestKey(config);

  // 节流检查：如果启用节流且存在相同的请求正在进行中，则复用该请求
  if (!config.disableThrottle && pendingRequests.has(requestKey)) {
    console.log(`请求节流：复用正在进行的请求 ${requestKey}`);
    const existingRequest = pendingRequests.get(requestKey)!;
    return existingRequest as Promise<ApiResponse<T>>;
  }

  // 检查是否为图片请求
  const isImageRequest = config.header && config.header['Content-Type'] === 'image/png';

  // 请求拦截器：添加 token 等公共 header
  const token = uni.getStorageSync('access_token');
  // const token = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJsb2dpblR5cGUiOiJsb2dpbiIsImxvZ2luSWQiOiJ4Y3g6MTk2Njc1MjQwMjA4NjA4MDUxMyIsInJuU3RyIjoiVDY5UkJiWWhwakNEYldGVkhCRmp0cENDWmIzN3NObDkiLCJjbGllbnRpZCI6ImJlNzA1MmE3ZTRmODAyYzIwZGYxMGE4ZDEzMWFkYjEyIiwidGVuYW50SWQiOiIwMDAwMDAiLCJ1c2VySWQiOjE5NjY3NTI0MDIwODYwODA1MTMsInVzZXJOYW1lIjoiMTMxMTExMTExMTEifQ.YPfUDdPbi74BMFgkj8v7iGhcHiahaFzOGXayTNUaxJE'
  if (token) {
    config.header!.Authorization = `Bearer ${token}`;
    config.header!.Clientid = `be7052a7e4f802c20df10a8d131adb12`;
  }

  // 创建请求Promise并添加到pending列表
  const requestPromise = (async (): Promise<ApiResponse<T>> => {
    try {
      const res = await new Promise<UniApp.RequestSuccessCallbackResult>((resolve, reject) => {
        const requestOptions: UniApp.RequestOptions = {
          url: config.url,
          method: config.method as any,
          data: config.data,
          header: config.header,
          timeout: config.timeout,
          // 图片请求使用arraybuffer响应类型
          responseType: isImageRequest ? 'arraybuffer' : 'text',
          success: (res) => resolve(res),
          fail: (err) => reject(err)
        };
        uni.request(requestOptions);
      });

      // 响应拦截器：处理成功响应
      if (res.statusCode === 200) {
        // 图片请求特殊处理
        if (isImageRequest) {
          try {
            // 检查数据类型并转换为base64
            let base64: string;
            if (res.data instanceof ArrayBuffer) {
              base64 = uni.arrayBufferToBase64(res.data);
            } else if (typeof res.data === 'string') {
              // 如果已经是base64字符串，直接使用
              base64 = res.data;
            } else {
              throw new Error('无效的图片数据类型');
            }
            
            const imageData = base64.startsWith('data:') ? base64 : `data:image/png;base64,${base64}`;
            
            // 构造符合ApiResponse格式的响应
            const imageResponse: ApiResponse<ImageResponse> = {
              code: 200,
              msg: '获取图片成功',
              data: {
                imageData: imageData
              }
            };
            
            return imageResponse as ApiResponse<T>;
          } catch (error) {
            console.error('图片数据处理失败:', error);
            throw new Error('图片数据处理失败');
          }
        }
        
        // 普通JSON请求处理
        const responseData = res.data as ApiResponse<T>;
        
        if (responseData.code === 200) {
          return responseData;
        } else if (responseData.code === 401) {
          // 401 未授权，清空 token 并跳转到登录页
          uni.removeStorageSync('access_token');
          uni.removeStorageSync('userInfo');
          uni.showToast({ title: '登录已过期，请重新登录', icon: 'none' });
          setTimeout(() => {
            uni.reLaunch({
              url: '/pages/user/login'
            });
          }, 1500);
          throw new Error('登录已过期');
        } else {
          uni.showToast({ title: responseData.msg || '请求失败', icon: 'none' });
          throw new Error(responseData.msg || '请求失败');
        }
      } else {
        uni.showToast({ title: '网络异常', icon: 'none' });
        throw new Error('网络异常');
      }

    } catch (error: any) {
      // 避免重复显示错误提示，只在网络错误时显示
      if (!error.message || error.message === '网络异常') {
        uni.showToast({ title: error.message || '请求出错', icon: 'none' });
      }
      throw error;
    } finally {
      // 请求完成后从pending列表中移除
      pendingRequests.delete(requestKey);
    }
  })();

  // 如果启用节流，将请求添加到pending列表
  if (!config.disableThrottle) {
    pendingRequests.set(requestKey, requestPromise);
  }

  return requestPromise;
};

export default request;
export type { RequestConfig, ApiResponse, ImageResponse };